using System;
using System.Collections;
using System.Data;
using System.Text;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.InsightWebControls;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.SearchContext;
using PHSRAG.Security.Enumerations;
using PHSRAG.Utility;
using PHSRAG.WebControls;
using Constants = PHSRAG.Insight21.InsightUtilities.Constants;

namespace PHSRAG.Insight21.Agreements
{
    /// <summary>
    /// The AgreementsSummary object is the class supporting the like-named page. It displays a summary view of all
    /// agreements the user has access to, and allows viewing the details of any such agreement.
    /// </summary>
    /// <remarks>
    /// The AgreementsSummary page supports searching/filtering the agreement list based on user-defined and user-selectable
    /// search criteria. Following is the list of such criteria:
    /// <list type="bullet">
    /// <item><description>Fund number (free-form entry)</description></item>
    /// <item><description>Sponsor number (free-form entry)</description></item>
    /// <item><description>PI (select from a DataGrid)</description></item>
    /// <item><description>Lab (select from a DataGrid)</description></item>
    /// <item><description>COS (select from a Tree)</description></item>
    /// <item><description>Status (select from a drop-down list)</description></item>
    /// <item><description>Sponsor name (free-form entry)</description></item>
    /// <item><description>Sponsor type (select from a drop-down list)</description></item>
    /// <item><description>Agreement type (select from a drop-down list)</description></item>
    /// <item><description>Activity type (select from a drop-down list)</description></item>
    /// <item><description>Location (select from a drop-down list)</description></item>
    /// <item><description>Project start and end dates (select from a calendar)</description></item>
    /// <item><description>Budget start and end dates (select from a calendar)</description></item>
    /// <item><description>BICS number (free-form entry)</description></item>
    /// <item><description>Walker number (free-form entry)</description></item>
    /// <item><description>Balance less than (free-form entry)</description></item>
    /// <item><description>Include program projects (select from check box)</description></item>
    /// </list>
    /// </remarks>
    public partial class AgreementsSummary : NoCachePage
    {
        #region Private Types

        private enum ColumnIndex
        {
            AgreementID,
            FundNumber,
            PIName,
            SponsorName,
            LinkButton,
            Title,
            ProjectStartDate,
            ProjectEndDate,
            BudgetStartDate,
            BudgetEndDate,
            AgreementType,
            ActivityType,
            StatusType,
            AccessLevel
        }

        /// <summary>
        /// Report types supported by the page.
        /// </summary>
        private enum ReportType
        {
            Excel,
            PDF
        }

        #endregion

        #region Constants

        private const string CurrentPageIndexKey = "currentPageIndexKey_27447545-6976-4179-A0A7-B3AFED489466";
        private const string ExcelReportControlFilePath = "../../Agreements/Reports/FinancialSummaryExcel.ascx";
        private const string PageName = "Agreement Summary";
        private const string SearchCriteriaVersionKey = "SearchCriteriaVersion_27447545-6976-4179-A0A7-B3AFED489466";
        private const string SearchCriteriaVersionKeyFin = "SearchCriteriaVersion_12B90EAE-E704-444a-8733-800F3F39866C";
        private const string SelectAgreementCommand = "SelectAgreement";
        private const string SponsorGroupTypeKey = "sponsorGroupType_27447545-6976-4179-A0A7-B3AFED489466";

        #endregion

        #region Instance Variables (Protected)

        private ExpansionToggler expansionToggler;

        #endregion

        #region Instance Variables (Private)

        private ICachePolicy cachePolicy;
        private ICachePolicy pageCachePolicy;

        #endregion

        #region Private Properties

        /// <summary>
        /// Get the Agreements (summary of agreements) that the logged-in user has access to. The list of agreements is
        /// is maintained by the Agreements business object within its data container. The Agreements object is cached.
        /// </summary>
        private AgreementSummaries AgreementSummaries
        {
            get
            {
                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                int searchVersion = searchCriteria.Version;

                AgreementSummaries agreementSummaries = ResultsCache.GetObject(cachePolicy, AgreementSummaries.CacheKey) as AgreementSummaries;
                if (agreementSummaries == null || (searchVersion != SearchCriteriaVersion))
                {
                    SearchCriteriaVersion = searchVersion;

                    ResultsCache.PurgeObject(cachePolicy);

                    searchCriteria[Constants.PIIDKey] = searchCriteria["piName"];
                    agreementSummaries = new AgreementSummaries();
                    agreementSummaries.Search(searchCriteria, Session.SessionID);

                    ResultsCache.SetObject(cachePolicy, AgreementSummaries.CacheKey, agreementSummaries);
                }

                return agreementSummaries;
            }
        }

        /// <summary>
        /// Get/Set the current page within the datagrid for display. This information persists across page loads.
        /// </summary>
        private int CurrentPageIndex
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.AgreementSummaryPageKey) as Hashtable;
                return (h == null || h[CurrentPageIndexKey] == null) ? 0 : (int) h[CurrentPageIndexKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.AgreementSummaryPageKey) as Hashtable ?? new Hashtable();
                h[CurrentPageIndexKey] = value;
                dataGrid.CurrentPageIndex = value;
                pageCachePolicy.Cache(Keys.AgreementSummaryPageKey, h);
            }
        }

        /// <summary>
        /// Gets/sets the SponsorGroupTypeId that is selected in the view bar.
        /// </summary>
        private int SponsorGroupTypeId
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.AgreementSummaryPageKey) as Hashtable;
                return (h == null || h[SponsorGroupTypeKey] == null) ? 0 : (int) h[SponsorGroupTypeKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.AgreementSummaryPageKey) as Hashtable ?? new Hashtable();

                h[SponsorGroupTypeKey] = value;
                pageCachePolicy.Cache(Keys.AgreementSummaryPageKey, h);
            }
        }

        /// <summary>
        /// Gets/sets an integer value indicating the search criteria version. 
        /// The version number changes when the search criteria changes.  This signals the page to re-build its
        /// cache.
        /// </summary>
        /// <remarks>
        /// This and All properties required to re-establish the page are stored as name / value pairs in
        /// a hash table stored in the session cache under the key Keys.FinancialSummaryPageKey.  
        /// This enables the page to re-establish its state with minimal IO to what it was when
        /// the user last visited it.
        /// </remarks>
        private int SearchCriteriaVersion
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.AgreementSummaryPageKey) as Hashtable;
                return (h == null || h[SearchCriteriaVersionKey] == null) ? 0 : (int) h[SearchCriteriaVersionKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.AgreementSummaryPageKey) as Hashtable ?? new Hashtable();
                h[SearchCriteriaVersionKey] = value;
                pageCachePolicy.Cache(Keys.AgreementSummaryPageKey, h);
                Hashtable h1 = pageCachePolicy.GetCachedObject(Keys.FinancialSummaryPageKey) as Hashtable ?? new Hashtable();
                h1[SearchCriteriaVersionKeyFin] = value;
                pageCachePolicy.Cache(Keys.FinancialSummaryPageKey, h1);
            }
        }

        /// <summary>
        /// Gets the boolean value, to decide whether or not to load the grid
        /// </summary>
        public bool IsOkayToLoadGrid
        {
            get
            {
                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                if (null == searchContext)
                {
                    return false;
                }

                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                UserContext userContext = cachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;

                return !(userContext.ShouldPromptForResourceSearch(Constants.Modules.Agreements) && searchCriteria.Count < 3 && (searchCriteria.Version <= 0 || SearchCriteriaVersion == -1));
            }
        }

        /// <summary>
        /// Gets the boolean value, to decide whether or not to display Overview Pages
        /// </summary>
        public bool IsOkayToShowOverview
        {
            get
            {
                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                if (null == searchContext)
                {
                    return false;
                }

                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                UserContext userContext = cachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;

                if (!(userContext.ShouldPromptForResourceSearch(Constants.Modules.Agreements) && searchCriteria.Count < 3))
                {
                    AgreementSummaries agreementSummaries =
                        ResultsCache.GetObject(cachePolicy, AgreementSummaries.CacheKey) as AgreementSummaries;

                    if (null != agreementSummaries)
                    {
                        if (agreementSummaries.Count > Settings.GetKeyValue(Keys.AgreementSummaryOverviewLimitKey, 0))
                        {
                            if (0 != (userContext.ModuleRoleBitmask & (int) ModuleRoleBit.NoAgreementOverviewLimit))
                            {
                                return true;
                            }
                        }
                        else
                        {
                            return true;
                        }
                    }
                }

                return false;
            }
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Handler for the event raised by the CommonSearch control when the "Clear Selection" buttion is clicked upon.
        /// The control clears the criretria (specific to this module).
        /// Since in the page life-cycle, the Load occurs before the Clear event, we have to instigate a re-load of the
        /// data grid to refelect the fact that the search criteria has been cleared.
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnClearSelection(object sender, CommandEventArgs e)
        {
            SearchCriteriaVersion = -1;

            dataGrid.DataSource = null;
            dataGrid.DataBind();
            downloadBar.Visible = false;
            ManagePagination();
            expandingPanel.IsExpanded = true;
            agreementsSubNavigation.EnableOverviewNavigation = false;
            expansionToggler = (ExpansionToggler) expandingPanel.FindControl("expansionToggler");
            if (expansionToggler != null)
            {
                if (!IsOkayToLoadGrid)
                {
                    expansionToggler.ShowOverViewHeaderHint = true;
                }
            }
        }

        /// <summary>
        /// Invoked by the download bar when it catches an exception.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnDownloadFailed(object sender, CommandEventArgs e)
        {
            annunciator.Title = "Following error(s) occurred while downloading";
            annunciator.Message = ExceptionReport.GetExceptionInfo((Exception) e.CommandArgument, false);
        }

        /// <summary>
        /// Handler for the event raised when the FirstPage link in clicked in the Pager control.
        /// Set the current page index to 0, bind the datagrid with data and manage navigation links. To avoid superfluous
        /// data binding activites, no action is taken if the current page index is already 0.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnFirstPage(object sender, CommandEventArgs e)
        {
            CurrentPageIndex = 0;
            LoadDataGrid();
        }

        /// <summary>
        /// Handler for event raised while each data grid item is created.
        /// If the item being created is the data grid header, do the following:
        /// Add the appropriate sort symbol to denote ascending/descending sequence for the current sort column.
        /// This requires us to locate the cell which corresponding to the column within the collection of TableCell
        /// maintained by the DataGridItem which is under creation. That collection is indexed numerically, the value being
        /// the position of the column within the columns collection maintained by the data grid.
        /// One simple way to do this is to create static mapping between the name of the column and its index. However, this
        /// suffers from the shortcoming that if the sequence of columns is changed on the page, the static binding MUST
        /// be changed too. If they get out of sync, we would be sorting on inappropriate columns!
        /// To avoid this, and to render the code independent of how the page gets managed, we will build a Hashtable of
        /// column indeces, keyed by the sort expression of each column. That way, we could do a quick lookup to get the
        /// index of a column and set the sort symbol on that column.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnItemCreated(object sender, DataGridItemEventArgs e)
        {
            if (dataGrid.Visible)
            {
                if (e.Item.ItemType == ListItemType.Header)
                {
                    // Ideally, we would like to set the width of each column such that the header text does not wrap. This
                    // is pretty easy, as evidenced by the following (commented) block of code. Why then is the code commented?
                    // Well, this gets us into an interesting pickle. Let me elucidate:
                    // When column widths are not explictly set, the header text MIGHT wrap, but when the size of the browser
                    // window is increased, column widths also increase, automatically filling the increased space. This is the
                    // desired behavior. However, if the column widths are EVER set explicitly, the contents won't expand to
                    // fill the available space. The rendered HTML will have the "Width" setting, and that clamsp the width
                    // hard. This is NOT the desired behavior.
                    // It therefor appers that we can either have the cake or eat it. I have decided to eat the cake and not
                    // set column width. Hence the block of code is commented.
                    // Why then, you ask, is the code still here? Just to show you it COULD be done with the mentioned caveat.
                    //				Bitmap bm = new Bitmap(1, 1);
                    //				Graphics g = Graphics.FromImage(bm);
                    //
                    //				for (int c = 0; c < dataGrid.Columns.Count; ++c)
                    //				{
                    //					SizeF size = g.MeasureString(dataGrid.Columns[c].HeaderText, new Font("Verdana", 10));
                    //					dataGrid.Columns[c].ItemStyle.Width = Unit.Pixel((int)Math.Ceiling(size.Width));
                    //				}

                    AgreementSummaries agreementSummaries = AgreementSummaries;
                    Label sortSymbol = new Label();
                    sortSymbol.CssClass = "Sort";
                    sortSymbol.Text = agreementSummaries.SortAscending ? Constants.SortAscendingText : Constants.SortDescendingText;
                    sortSymbol.Font.Name = Constants.SortSymbolFontName;

                    Hashtable columnMap = new Hashtable();
                    foreach (DataGridColumn column in dataGrid.Columns)
                    {
                        columnMap[column.SortExpression] = dataGrid.Columns.IndexOf(column);
                    }

                    string sortColumn = agreementSummaries.SortColumn;
                    if (columnMap.ContainsKey(sortColumn))
                    {
                        (e.Item.Cells[(int) columnMap[sortColumn]]).Controls.Add(sortSymbol);
                    }
                }
                //				else if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
                //				{
                //					//Disable view state for all but the columns which hold agreement ID, fund number, budget start date,
                //					//and access level (which are retrieved while navigating to the detail page).
                //					for (int i = 0, cellCount = e.Item.Cells.Count; i < cellCount; ++i)
                //						if ((i != (int)ColumnIndex.AgreementID) && 
                //							(i != (int)ColumnIndex.FundNumber) && 
                //							(i != (int)ColumnIndex.AccessLevel) &&
                //							i != (int)ColumnIndex.BudgetStartDate)
                //							e.Item.Cells[i].EnableViewState = false;
                //				}
            }
        }

        /// <summary>
        /// Handler for the event raised when a row in the datagrid is clicked upon.
        /// If the "Project Title" link was clicked upon (its CommandName is "SelectAgreement"), load the AgreementDetail
        /// page passing it the selected agreement ID through a dictionary.
        /// </summary>
        /// <param name="source">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnItemCommand(object source, DataGridCommandEventArgs e)
        {
            if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
            {
                if (e.CommandName == SelectAgreementCommand)
                {
                    Hashtable dictionary = new Hashtable();
                    dictionary.Add(Keys.AgreementIdKey, Convert.ToInt32(e.Item.Cells[(int) ColumnIndex.AgreementID].Text));
                    dictionary.Add(Keys.FundNumberKey, e.Item.Cells[(int) ColumnIndex.FundNumber].Text);
                    dictionary.Add(Keys.JournalEndDateKey, refreshDates.GLPostAsOfDate.ToShortDateString());
                    dictionary.Add(Keys.RevenueEndDateKey, refreshDates.GLPostAsOfDate.ToShortDateString());
                    dictionary.Add(Keys.SalaryAsOfDateKey, refreshDates.SalaryAsOfDate.ToShortDateString());
                    dictionary.Add(Constants.AgreementsConstants.AccessRightsKey, Convert.ToInt32(e.Item.Cells[(int) ColumnIndex.AccessLevel].Text));
                    dictionary.Add(Keys.RefreshBudgetDetailDataKey, true);

                    string budgetStartDate = (e.Item.Cells[(int) ColumnIndex.BudgetStartDate].Text == "&nbsp;") ? string.Empty : e.Item.Cells[(int) ColumnIndex.BudgetStartDate].Text;
                    dictionary.Add(Keys.BudgetYearKey, (budgetStartDate == string.Empty) ? 0 : Convert.ToDateTime(budgetStartDate).Year);
                    dictionary.Add(Keys.JournalStartDateKey, "1/1/1900");
                    dictionary.Add(Keys.RevenueStartDateKey, "1/1/1900");

                    pageCachePolicy.Cache(Constants.AgreementsConstants.AgreementDetailsKey, dictionary);

                    PurgeCache();
                    Response.Redirect(Settings.GetKeyValue("SubNavigation.Agreements.ProjectDetailsURL", ""));
                }
            }
        }

        /// <summary>
        /// Handler for the ItemDataBound event that is raised after an item is data bound to the DataGrid control. 
        /// This event provides us with the last opportunity to access the data item before it is displayed on the client.
        /// It is here that we add the Full Title tool tip that gets displayed when a mouse over occurs on a cell in 
        /// the Project Title column.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnItemDataBound(object sender, DataGridItemEventArgs e)
        {
            try
            {
                if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem
                    && dataGrid.Visible)
                {
                    ((LinkButton) e.Item.Cells[(int) ColumnIndex.LinkButton].Controls[0]).ToolTip =
                        string.Format("Full Title: {0}", e.Item.Cells[(int) ColumnIndex.Title].Text);

                    // The AgreementSummary object (the data source for each item) return string.Empty for FundNumber when it
                    // is not specified for the agreement. However, when bound, this will translate to "&nbsp;". When we then
                    // retrieve the fund number in OnItemCommand, we get "&nbsp;" which then is merrily passed along with
                    // fairly disastrous affects. So, set the cell value to null if there is no fund number.

                    AgreementSummary agreementSummary = (AgreementSummary) e.Item.DataItem;
                    if (agreementSummary.FundNumber == string.Empty)
                    {
                        e.Item.Cells[(int) ColumnIndex.FundNumber].Text = null;
                    }

                    if (agreementSummary.BudgetStartDate == string.Empty)
                    {
                        e.Item.Cells[(int) ColumnIndex.BudgetStartDate].Text = null;
                    }
                }
            }
            catch (Exception ex)
            {
                annunciator.Message = String.Format("{0} while attempting to format columns.",
                    ExceptionReport.GetExceptionInfo(ex, false));
            }
        }

        /// <summary>
        /// Handler for the event raised when the LastPage link in clicked in the Pager control.
        /// Set the current page index to one less than the total page count (index is 0-based), bind the datagrid with
        /// data and manage navigation links. To avoid superfluous data binding activites, no action is taken if the current
        /// page index is already corresponding to the last page.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnLastPage(object sender, CommandEventArgs e)
        {
            CurrentPageIndex = pagerAboveDatagrid.PageCount - 1;
            LoadDataGrid();
        }

        /// <summary>
        /// Handler for the event raised when the page is being loaded.
        /// Initialize the bread crumb control, set the page size for the data grid, and load the data grid with data.
        /// If on the first page within the data grid, initalize the pager control. Notice that even when in the context
        /// of a non-postback load, the current page index may not be 0 since the page index is restored from the cache.
        /// The data grid is loaded with data on every page load because the data grid is set not to use ViewState.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                annunciator.Message = string.Empty;

                breadCrumb.Add(PageName,
                    Settings.GetKeyValue("SubNavigation.Agreements.AgreementSummaryURL", ""),
                    Settings.GetKeyValue("BreadCrumb.SummaryPageLevel", 1));

                if (!IsPostBack)
                {
                    dataGrid.PageSize = Settings.GetKeyValue("DataGrid.ItemsPerPage", 20);

                    ((ExpansionToggler) expandingPanel.FindControl("expansionToggler")).HelpText =
                        Constants.SearchHelpText;

                    expansionToggler = (ExpansionToggler) expandingPanel.FindControl("expansionToggler");

                    if (IsOkayToLoadGrid)
                    {
                        downloadBar.Visible = true;
                        if (expansionToggler != null)
                        {
                            expansionToggler.ShowOverViewHeaderHint = false;
                        }

                        expandingPanel.IsExpanded = false;
                        //set the Agreement Status to Awarded in search criteria display
                        CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                        AgreementSearchContext agreementSearchContext = (AgreementSearchContext) cachePolicy.GetCachedObject(AgreementSearchContext.CacheKey);
                        SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());

                        if (searchCriteria.Version < 1)
                        {
                            DataRow[] dataRows = agreementSearchContext.AgreementStatusData.Select("StatusTypeId=3");
                            if (dataRows.Length > 0)
                            {
                                string awardedText = dataRows[0]["StatusType"].ToString();
                                if (searchCriteria[Constants.AgreementStatusIDKey] == null)
                                {
                                    searchContext.SetPrimarySearchCriteria(SearchCriteria.Level.Summary,
                                        Page.Request.Url.ToString(),
                                        Constants.AgreementStatusIDKey, "3", "Agreement Status",
                                        CommonSearch.LabelValueSeparator, awardedText);
                                }
                            }
                        }

                        LoadDataGrid();

                        agreementsSubNavigation.EnableOverviewNavigation = IsOkayToShowOverview;
                    }
                    else
                    {
                        if (expansionToggler != null)
                        {
                            expansionToggler.ShowOverViewHeaderHint = true;
                        }

                        ManagePagination();
                        expandingPanel.IsExpanded = true;
                        agreementsSubNavigation.EnableOverviewNavigation = false;
                        downloadBar.Visible = false;
                    }

                    // get rid of the details keys, item command event handler will recreate if needed.
                    pageCachePolicy.UnCache(Constants.AgreementsConstants.AgreementDetailsKey);

                    // Reset the sub-navigation control such that on entry into this module, any hysterisis at the sub-navigation
                    // level from sibling modules does not prevail.

                    agreementsSubNavigation.ResetOverviewNavigation();
                }
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred during PageLoad:";
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
            finally
            {
                agreementsSubNavigation.SelectedLink = "Agreement Summary";
            }
        }

        /// <summary>
        /// Handler for the event raised when the NextPage link in clicked in the Pager control.
        /// Increment the current page index, bind the datagrid with data and manage navigation links.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnNextPage(object sender, CommandEventArgs e)
        {
            ++CurrentPageIndex;
            LoadDataGrid();
        }

        /// <summary>
        /// Handler for the event raised when the PreviousPage link in clicked in the Pager control.
        /// Decrement the current page index, bind the datagrid with data and manage navigation links.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnPreviousPage(object sender, CommandEventArgs e)
        {
            --CurrentPageIndex;
            LoadDataGrid();
        }

        /// <summary>
        /// Gets the search criteia and performs a search. The actual search is performed by the AgreementSummaries object
        /// which also returns true if it did indeed apply any filteration criteria, and false otherwise. This predicate
        /// is used by LoadDataGrid() to control the visibility of the pager controls.
        /// </summary>
        /// <param name="args">Contains the search criteria</param>
        protected void OnSearch(SearchCriteriaArgs args)
        {
            if (SearchCriteriaVersion == -1)
            {
                ++SearchCriteriaVersion;
            }
            CommonSearchContext searchContext = cachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;
            if (searchContext != null)
            {
                expansionToggler = (ExpansionToggler) expandingPanel.FindControl("expansionToggler");
            }

            CurrentPageIndex = 0;
            LoadDataGrid();

            if (IsOkayToShowOverview)
            {
                if (expansionToggler != null)
                {
                    expansionToggler.ShowOverViewHeaderHint = false;
                }

                agreementsSubNavigation.EnableOverviewNavigation = true;
            }
            else
            {
                if (expansionToggler != null)
                {
                    expansionToggler.ShowOverViewHeaderHint = true;
                }

                agreementsSubNavigation.EnableOverviewNavigation = false;
            }
        }

        /// <summary>
        /// Handler for the event raised when a column header within the data grid is clicked.
        /// Sorting of data is carried out by the Agreements object itself (since it maintains the data anyway).
        /// Set the current page index to 0, load the data grid, and initialize the pager. We set the page index to 0
        /// since sorting implies sorting of the entrie data and NOT sorting what is visible.
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        protected void OnSort(object source, DataGridSortCommandEventArgs e)
        {
            if (e.SortExpression != string.Empty)
            {
                AgreementSummaries.Sort(e.SortExpression);
                CurrentPageIndex = 0;
                LoadDataGrid();
            }
        }

        /// <summary>
        /// Purges the cache and sets the correct search context level before the breadcrumb performs a redirect.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void OnNavigate(object sender, CommandEventArgs e)
        {
            if (((CommandEventArgs) (e.CommandArgument)).CommandName == Convert.ToString((int) SearchCriteria.Level.Summary))
            {
                //set the search context's level to the correct level
                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                searchContext.CurrentLevel = SearchCriteria.Level.Summary;
            }
            PurgeCache();
        }

        /// <summary>
        /// Resets the Agreements subnavigation selected link before the 
        /// header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnHeaderNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
            agreementsSubNavigation.Reset();
        }

        /// <summary>
        /// Purges the cache before the agreements subnavigation header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnSubNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// GetFinancialSummaryResultset instanciates the FinancialSummaries object and returns a resultset.
        /// </summary>
        /// <returns>FinancialSummaries DataSet</returns>
        private DataSet GetFinancialSummaryResultset()
        {
            FinancialSummaries financialSummaries = new FinancialSummaries();
            try
            {
                UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);
                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                if (searchCriteria[Constants.DomainUserIDKey] == null || searchCriteria[Constants.DomainUserIDKey] == "0")
                {
                    searchCriteria.Add(Constants.DomainUserIDKey, Convert.ToString(userContext.DomainUserId));
                }

                //@@@JGC TODO : figure out cost option (Include Indirect) 
                financialSummaries.DepracatedLoad(
                    DataAccess.GetConnectionString()
                    , searchCriteria
                    , refreshDates.GLPostAsOfDate.ToShortDateString() // GL Post As Of Date
                    , null //Convert.ToBoolean(costOption.SelectedValue)				// Include Indirect
                    , true // get a Financial-AgreementSummary hybrid report
                    );
            }
            catch (Exception e)
            {
                throw new Exception(e.Message, e.InnerException);
            }

            return financialSummaries.GetDataContainer();
        }

        /// <summary>
        /// Load the datagrid with sufficient data for display within one page of the data grid. This is done as follows:
        /// Get the summaries for all agreements that the user has access to. Use that to initialize the data grid and
        /// the pager controls based on the page size of the data grid.
        /// The pagers are made visible only when more than one page of data can be displayed.
        /// If there is no data to display, warn the user via the annunciator.
        /// </summary>
        private void LoadDataGrid()
        {
            try
            {
                AgreementSummaries agreementSummaries = AgreementSummaries;
                dataGrid.VirtualItemCount = pagerBelowDatagrid.RecordCount = pagerAboveDatagrid.RecordCount = agreementSummaries.Count;

                int currentPageIndex = CurrentPageIndex;
                int pageCount = (pagerAboveDatagrid.RecordCount/dataGrid.PageSize) +
                    (((pagerAboveDatagrid.RecordCount%dataGrid.PageSize) == 0) ? 0 : 1);
                pagerBelowDatagrid.PageCount = pagerAboveDatagrid.PageCount = pageCount;
                pagerBelowDatagrid.CurrentPage = pagerAboveDatagrid.CurrentPage = currentPageIndex + 1;

                ArrayList agreementList = agreementSummaries.GetAgreementList(currentPageIndex*dataGrid.PageSize, dataGrid.PageSize);
                dataGrid.DataSource = agreementList;
                dataGrid.DataBind();

                ManagePagination();

                if (!dataGrid.Visible && SearchCriteriaVersion != -1)
                {
                    downloadBar.Visible = false;
                    dataGrid.Visible = false;
                    annunciator.Message = "No agreements found for the user";
                }
                else
                {
                    downloadBar.Visible = true;
                    dataGrid.Visible = true;
                }
            }
            catch (Exception e)
            {
                pagerBelowDatagrid.Visible = pagerAboveDatagrid.Visible = dataGrid.Visible = false;
                annunciator.Message = ExceptionReport.GetExceptionInfo(e, false);
            }
        }

        private void ManagePagination()
        {
            pagerBelowDatagrid.Visible = pagerAboveDatagrid.Visible = dataGrid.Visible = (dataGrid.Items.Count > 0 && SearchCriteriaVersion != -1);
            if (dataGrid.Visible)
            {
                int currentPageIndex = CurrentPageIndex;
                dataGrid.CurrentPageIndex = currentPageIndex;

                int startIndex = currentPageIndex*dataGrid.PageSize;

                pagerBelowDatagrid.FirstRecord = pagerAboveDatagrid.FirstRecord = startIndex + 1;
                pagerBelowDatagrid.LastRecord = pagerAboveDatagrid.LastRecord =
                    Math.Min(startIndex + dataGrid.PageSize, dataGrid.VirtualItemCount);

                pagerBelowDatagrid.EnableFirstPage = pagerAboveDatagrid.EnableFirstPage =
                    pagerBelowDatagrid.EnablePreviousPage = pagerAboveDatagrid.EnablePreviousPage =
                        (CurrentPageIndex != 0);

                pagerBelowDatagrid.EnableLastPage = pagerAboveDatagrid.EnableLastPage =
                    pagerBelowDatagrid.EnableNextPage = pagerAboveDatagrid.EnableNextPage =
                        (CurrentPageIndex != (pagerAboveDatagrid.PageCount - 1));
            }
        }

        /// <summary>
        /// Purge the cached BO from the cache and remove its key from the cache.
        /// </summary>
        private void PurgeCache()
        {
            System.Diagnostics.Trace.WriteLine("Purging AgreementSummary...");
            ResultsCache.PurgeObject(cachePolicy);
        }

        /// <summary>
        /// Adds refresh dates currently visible on the page to the search criteria string
        /// to be passed down to reports. The criteria does not persist to the SearchCriteria
        /// object.
        /// </summary>
        /// <param name="searchCriteria">Object containing search criteria.</param>
        /// <returns>A string representation of search criteria. </returns>
        private string AddRefreshDatesToCriteria(SearchCriteria searchCriteria)
        {
            StringBuilder criteria = new StringBuilder(searchCriteria.ToString(";"));
            if (refreshDates.SalaryAsOfDateVisible)
            {
                criteria.AppendFormat("Last Salary Post|{0};", refreshDates.SalaryAsOfDate.ToShortDateString());
            }
            if (refreshDates.GLAsOfDateVisible)
            {
                criteria.AppendFormat("Last GL Post|{0};", refreshDates.GLPostAsOfDate.ToShortDateString());
            }
            if (refreshDates.POAPAsOfDateVisible)
            {
                criteria.AppendFormat("Last PO/AP Post|{0};", refreshDates.POAPAsOfDate.ToShortDateString());
            }
            return criteria.ToString();
        }

        #endregion

        #region Web Form Designer generated code

        /// <summary>
        /// Handler for the event raised when the page is being initialized.
        /// Retrieve the cache policy in force. Deposit event handlers to support the datagrid pagination.
        /// </summary>
        /// <param name="e">Argument associated with the event</param>
        protected override void OnInit(EventArgs e)
        {
            InitializeComponent();
            base.OnInit(e);

            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];

            CommonSearch commonSearch = (CommonSearch) expandingPanel.FindControl("commonSearch");
            commonSearch.Field2AutoCompleteServicePath = Utility.Settings.GetKeyValue("CommonLookupWebservice", "");
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
        }

        #endregion
    }
}